/*
 * Copyright (C),2015,北京新诺创科软件技术有限公司
 * author zhangmengliang
 */
package com.xnck.mfpms.service;

import com.xiaoleilu.hutool.DateUtil;
import com.xiaoleilu.hutool.StrUtil;
import com.xnck.mfpms.dao.ActionDao;
import com.xnck.mfpms.dao.ActionResDao;
import com.xnck.mfpms.dao.ResTypeDao;
import com.xnck.mfpms.dao.ResourceDao;
import com.xnck.mfpms.entity.ActionInfo;
import com.xnck.mfpms.entity.ActionResource;
import com.xnck.mfpms.entity.ResourceInfo;
import com.xnck.mfpms.entity.ResourceType;
import com.xnck.mfpms.exception.ValidateException;
import com.xnck.mfpms.util.PagerUtil;
import com.xnck.mfpms.util.ValidatorUtils;
import org.nutz.dao.Cnd;
import org.nutz.dao.sql.Criteria;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Service
public class ResService {

    @Autowired
    private ResourceDao resDao;

    @Autowired
    private ActionDao actionDao;

    @Autowired
    private ResTypeDao resTypeDao;

    @Autowired
    private ActionResDao actionResDao;

    public List<ResourceType> getTypes(){
        return resTypeDao.search();
    }

    public ResourceInfo get(String resId){
        return resDao.get(resId);
    }

    public int getsCount(String resName){
        Criteria cri = Cnd.cri();
        this.getSearchCnd(cri, resName);
        return resDao.searchCount(cri);
    }

    public List<ResourceInfo> gets(String resName, String orderName, String orderType,
                                   int pageSize, int beginIndex){
        Criteria cri = Cnd.cri();
        this.getSearchCnd(cri, resName);
        PagerUtil.getSearchOrder(cri, ResourceInfo.FIELD_CODE, orderName, orderType);
        int currentPage = PagerUtil.getCurrentPage(beginIndex, pageSize);
        return resDao.searchByPage(cri, currentPage, pageSize);
    }

    /**
     * 创建资源
     * @param creatorId 创建者
     * @param displayName 显示名
     * @param code 编号
     * @param typeId 类型
     * @param viewName 所属页面视图
     * @param remark 备注
     * @param enable 是否启用
     * @throws Exception
     */
    @Transactional(rollbackFor = Exception.class)
    public void create(String creatorId, String displayName, String code, String typeId,
                       String viewName, String remark, boolean enable) throws Exception {
        this.checkResInsertInput(creatorId, displayName, code, viewName, remark);
        String resId = UUID.randomUUID().toString();
        Date addTime = DateUtil.date();
        resDao.insert(resId, displayName, code, typeId, viewName, remark, enable, addTime, creatorId);
    }

    /**
     * 修改
     */
    @Transactional(rollbackFor = Exception.class)
    public void update(String id, String displayName, String code, String typeId,
                       String viewName, String remark, boolean enable) throws Exception {
        this.checkResUpdatetInput(id, displayName, code, viewName, remark);
        ResourceInfo res = resDao.get(id);
        if (null == res){
            throw new ValidateException("资源不存在");
        }
        res.setViewname(viewName);
        res.setTypeid(typeId);
        res.setRemark(remark);
        res.setDisplayname(displayName);
        res.setCode(code);
        res.setEnable(enable);
        resDao.update(res);
    }

    /**
     * 删除
     * @param resIds
     * @throws Exception
     */
    @Transactional(rollbackFor = Exception.class)
    public void delete(String resIds) throws Exception {
        actionResDao.clear(Cnd.where(ActionResource.FIELD_RESOURCEID, "in", resIds.split(",")));
        resDao.clear(Cnd.where(ResourceInfo.FIELD_ID, "in", resIds.split(",")));
    }

    /**
     * 资源与权限的关联关系
     * @param resId
     * @return
     * @throws Exception
     */
    public List<Map<String, Object>> getActionNodes(String resId) throws Exception {
        ResourceInfo res = resDao.get(resId);
        if (null == res){
            throw new ValidateException("资源不存在");
        }
        List<ActionInfo> actions = actionDao.search(Cnd.orderBy().asc(ActionInfo.FIELD_DISPLAYNAME));
        resDao.findLink(res, ResourceInfo.FIELD_ACTIONS);
        List<Map<String, Object>> nodes = new ArrayList<Map<String, Object>>();
        for (ActionInfo action: actions) {
            Map<String, Object> node = new HashMap<String, Object>();
            node.put("id", action.getId());
            node.put("name", action.getDisplayname());
            node.put("pId", action.getParentid());
            boolean isChecked = false;
            for (ActionInfo joinAction : res.getActions()) {
                if (joinAction.getId().equals(action.getId())){
                    isChecked = true;
                }
            }
            node.put("checked", isChecked);
            nodes.add(node);
        }
        return nodes;
    }

    /**
     * 关联资源和权限
     * @param resId 被关联资源
     * @param actionIdStr 被关联权限列表(以逗号相隔)
     */
    @Transactional(rollbackFor = Exception.class)
    public void joinAction(String resId, String actionIdStr) throws Exception {
        ResourceInfo res = resDao.get(resId);
        if (null == res){
            throw new ValidateException("资源不存在");
        }
        if (StrUtil.isBlank(actionIdStr)){
            throw new ValidateException("权限不存在");
        }
        String[] actionIds = actionIdStr.split(",");
        resDao.clearLinks(res, ResourceInfo.FIELD_ACTIONS);
        List<ActionInfo> actions = actionDao.search(Cnd.where(ActionInfo.FIELD_ID, "in", actionIds));
        if (actions.size() > 0){
            res.setActions(actions);
            resDao.insertRelation(res, ResourceInfo.FIELD_ACTIONS);
        }
    }

    private void getSearchCnd(Criteria cri, String resName){
        if (StrUtil.isNotBlank(resName)){
            cri.where().and(
                    Cnd.exps(ResourceInfo.FIELD_DISPLAYNAME, "like", "%" + resName + "%")
                            .or(ResourceInfo.FIELD_CODE, "like", "%" + resName + "%"));
        }
    }

    private void checkResInsertInput(String creatorId, String displayName, String code, String viewName, String remark) throws Exception {
        if (ValidatorUtils.isEmpty(creatorId)){
            throw new ValidateException("创建者不存在");
        }
        if (ValidatorUtils.isEmpty(displayName)){
            throw new ValidateException("显示名不能为空");
        }
        if(displayName.getBytes().length < 4 || displayName.getBytes().length > 20){
            throw new ValidateException("显示名应由4-20个字符组成");
        }
        if (ValidatorUtils.isEmpty(code)){
            throw new ValidateException("代码不能为空");
        }
        if(code.getBytes().length < 4 || code.getBytes().length > 50){
            throw new ValidateException("代码应由4-50个字符组成");
        }
        if (!ValidatorUtils.isEmpty(viewName) && (viewName.getBytes().length < 4 || viewName.getBytes().length > 100)){
            throw new ValidateException("视图名称应由4-100个字符组成");
        }
        if (!ValidatorUtils.isEmpty(remark) && (remark.getBytes().length < 4 || remark.getBytes().length > 100)){
            throw new ValidateException("备注说明应由4-100个字符组成");
        }
        List<ResourceInfo> reses = resDao.search(Cnd.where(ResourceInfo.FIELD_CODE, "=", code));
        if (reses.size() > 0){
            throw new ValidateException("相同代码的资源已存在");
        }
    }

    private void checkResUpdatetInput(String id, String displayName, String code, String viewName, String remark) throws Exception {
        if (ValidatorUtils.isEmpty(displayName)){
            throw new ValidateException("显示名不能为空");
        }
        if(displayName.getBytes().length < 4 || displayName.getBytes().length > 20){
            throw new ValidateException("显示名应由4-20个字符组成");
        }
        if (ValidatorUtils.isEmpty(code)){
            throw new ValidateException("显示名不能为空");
        }
        if(code.getBytes().length < 4 || code.getBytes().length > 50){
            throw new ValidateException("显示名应由4-50个字符组成");
        }
        if (!ValidatorUtils.isEmpty(viewName) && (viewName.getBytes().length < 4 || viewName.getBytes().length > 100)){
            throw new ValidateException("视图名称应由4-100个字符组成");
        }
        if (!ValidatorUtils.isEmpty(remark) && (remark.getBytes().length < 4 || remark.getBytes().length > 100)){
            throw new ValidateException("备注说明应由4-100个字符组成");
        }
        List<ResourceInfo> reses = resDao.search(Cnd.where(ResourceInfo.FIELD_CODE, "=", code)
                .and(ResourceInfo.FIELD_ID, "<>", id));
        if (reses.size() > 0){
            throw new ValidateException("相同代码的资源已存在");
        }
    }
}
